"""
$Id: $
"""
from zope import interface
from zope import event
from zope.lifecycleevent import ObjectCreatedEvent

from sqlalchemy import orm
from ore.alchemist import container
from ore.alchemist import Session
from zope.security.proxy import removeSecurityProxy

from i18n import _

import interfaces, factory



class Versioned(container.PartialContainer):
    interface.implements(interfaces.IVersioned)
    
    def _copyFields( self, source, dest):
        kls = source.__class__
        table = orm.class_mapper(kls).mapped_table

        for column in table.columns:
            if column.primary_key:
                continue

            value = getattr(source, column.name)
            setattr(dest, column.name, value)


    def create( self, message, manual = False ):
        """Store the existing state of the adapted context as a new
        version."""

        version = self.domain_model()
        context = self.__parent__
        trusted = removeSecurityProxy(context)
        
        # set values on version from context
        self._copyFields(trusted, version)
        
        # content domain ids are typically not in the interfaces
        # manually inspect and look for one, by hand to save on the new version
        mapper = orm.object_mapper(trusted)
        version.content_id = mapper.primary_key_from_instance(trusted)[0]
        version.status = None
        version.manual = manual
        
        # we rely on change handler to attach the change object to the version
        event.notify(
            interfaces.VersionCreated(context, self, version, message))
                                                   
        session = Session()
        session.add(version)
        
        version.context = context        
        event.notify(ObjectCreatedEvent(version))

        return version

        
    def revert( self, version, message ):
        """Revert the current state of the adapted object to the
        values specified in version, and create a new version with
        reverted state."""

        context = self.__parent__
        trusted = removeSecurityProxy(context)
        ctx_class = trusted.__class__
        
        has_wf_status = hasattr(context, 'status')
        if has_wf_status:
            wf_status = context.status
            
        # set values on version from context
        self._copyFields(version, trusted)

        if has_wf_status:
            context.status = wf_status
            
        msg = _(u"Reverted to previous version $version.",
                mapping={'version': version.version_id})

        event.notify(
            interfaces.VersionReverted(context, self, version, msg))
        
        self.create(message=msg)

class ContentVersionsFactory( object ):

    def __call__( self, context ):
        content_version_class = getattr(
            domain, context.__class__.__name__ + "Version")
        
        versions = Versioned()
        versions._class = content_version_class 
        trusted_ctx = removeSecurityProxy( context )
        mapper = orm.object_mapper( trusted_ctx )
        pk_value = mapper.primary_key_from_instance( trusted_ctx )[0]
        versions.setQueryModifier(
            content_version_class.c[ "content_id" ] == pk_value)
        versions.__parent__ = context
        versions.__name__ = 'versions'
        return versions

ContextVersioned = ContentVersionsFactory()

